"""笔记分享模块的视图

定义笔记分享相关的API视图，包括分享创建、管理、访问等。
"""

from rest_framework import status, permissions
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from django.db.models import Q, F
from django.utils import timezone
from django.shortcuts import get_object_or_404
from django.db import transaction

from .models import SharedNote, SharedFolder, ShareComment, ShareAccess, CommentLike
from .serializers import (
    SharedNoteSerializer,
    SharedFolderSerializer,
    SharedFolderCreateSerializer,
    SharedFolderAccessSerializer,
    ShareCommentSerializer,
    ShareAccessSerializer,
    CommentLikeSerializer
)
from apps.notes.models import Note, Category
from apps.common.models import ActivityLog


class SharedFolderViewSet(ModelViewSet):
    """共享文件夹视图集
    
    处理文件夹分享的创建、管理和访问。
    """
    
    serializer_class = SharedFolderSerializer
    permission_classes = [permissions.IsAuthenticated]
    
    def get_queryset(self):
        """获取查询集"""
        return SharedFolder.objects.filter(
            shared_by=self.request.user
        ).select_related('category', 'shared_by').order_by('-created_at')
    
    def get_serializer_class(self):
        """根据动作选择序列化器"""
        if self.action == 'create':
            return SharedFolderCreateSerializer
        elif self.action == 'access':
            return SharedFolderAccessSerializer
        return SharedFolderSerializer
    
    @transaction.atomic
    def create(self, request, *args, **kwargs):
        """创建共享文件夹"""
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        # 检查文件夹是否存在
        category_id = serializer.validated_data['category'].id
        category = get_object_or_404(
            Category,
            id=category_id,
            created_by=request.user
        )
        
        # 检查是否已经分享过
        existing_share = SharedFolder.objects.filter(
            category=category,
            shared_by=request.user
        ).first()
        
        if existing_share:
            return Response(
                {'error': '该文件夹已经分享过了'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        shared_folder = serializer.save()
        
        # 记录活动日志
        ActivityLog.objects.create(
            user=request.user,
            action='share_folder',
            content_object=shared_folder,
            description=f'分享了文件夹: {shared_folder.category.name}'
        )
        
        # 返回完整的序列化数据
        response_serializer = SharedFolderSerializer(shared_folder)
        return Response(
            response_serializer.data,
            status=status.HTTP_201_CREATED
        )
    
    @transaction.atomic
    def update(self, request, *args, **kwargs):
        """更新共享设置"""
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        
        # 检查权限
        if instance.shared_by != request.user:
            return Response(
                {'error': '无权限修改此分享'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        serializer = self.get_serializer(
            instance,
            data=request.data,
            partial=partial
        )
        serializer.is_valid(raise_exception=True)
        serializer.save()
        
        return Response(serializer.data)
    
    @transaction.atomic
    def destroy(self, request, *args, **kwargs):
        """删除分享"""
        instance = self.get_object()
        
        # 检查权限
        if instance.shared_by != request.user:
            return Response(
                {'error': '无权限删除此分享'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        # 记录活动日志
        ActivityLog.objects.create(
            user=request.user,
            action='unshare_folder',
            description=f'取消分享文件夹: {instance.category.name}'
        )
        
        instance.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)
    
    @action(detail=False, methods=['get'])
    def by_token(self, request):
        """通过token获取共享文件夹"""
        token = request.query_params.get('token')
        if not token:
            return Response(
                {'error': '缺少分享令牌'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        try:
            shared_folder = SharedFolder.objects.select_related(
                'category', 'shared_by'
            ).get(share_token=token)
        except SharedFolder.DoesNotExist:
            return Response(
                {'error': '分享不存在'},
                status=status.HTTP_404_NOT_FOUND
            )
        
        # 检查分享是否可访问
        if not shared_folder.can_access():
            return Response(
                {'error': '分享已失效'},
                status=status.HTTP_410_GONE
            )
        
        serializer = self.get_serializer(shared_folder)
        return Response(serializer.data)
    
    @action(detail=True, methods=['post'])
    def access(self, request, pk=None):
        """访问共享文件夹"""
        shared_folder = self.get_object()
        
        # 验证访问权限
        serializer = SharedFolderAccessSerializer(
            data=request.data,
            context={'shared_folder': shared_folder}
        )
        serializer.is_valid(raise_exception=True)
        
        # 增加访问计数
        shared_folder.increment_view_count(is_unique_visitor=True)
        
        # 返回文件夹内容
        from apps.notes.serializers import NoteSerializer
        notes = Note.objects.filter(
            category=shared_folder.category,
            status='published'
        ).order_by('-updated_at')
        
        note_serializer = NoteSerializer(notes, many=True)
        
        return Response({
            'folder': SharedFolderSerializer(shared_folder).data,
            'notes': note_serializer.data
        })
    
    @action(detail=False, methods=['get'])
    def my_shares(self, request):
        """获取我的分享列表"""
        queryset = self.get_queryset()
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)


class SharedNoteViewSet(ModelViewSet):
    """分享笔记视图集
    
    处理笔记分享的创建、管理和访问。
    """
    
    serializer_class = SharedNoteSerializer
    permission_classes = [permissions.IsAuthenticated]
    
    def get_queryset(self):
        """获取查询集"""
        return SharedNote.objects.filter(
            shared_by=self.request.user
        ).select_related('note', 'shared_by').order_by('-created_at')
    
    @transaction.atomic
    def create(self, request, *args, **kwargs):
        """创建分享"""
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        # 设置分享者
        serializer.validated_data['shared_by'] = request.user
        
        shared_note = serializer.save()
        
        # 记录活动日志
        ActivityLog.objects.create(
            user=request.user,
            action='share_note',
            content_object=shared_note,
            description=f'分享了笔记: {shared_note.note.title}'
        )
        
        return Response(
            serializer.data,
            status=status.HTTP_201_CREATED
        )
    
    @transaction.atomic
    def update(self, request, *args, **kwargs):
        """更新分享设置"""
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        
        # 检查权限
        if instance.shared_by != request.user:
            return Response(
                {'error': '没有权限修改此分享'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        serializer = self.get_serializer(
            instance, data=request.data, partial=partial
        )
        serializer.is_valid(raise_exception=True)
        serializer.save()
        
        return Response(serializer.data)
    
    @transaction.atomic
    def destroy(self, request, *args, **kwargs):
        """删除分享"""
        instance = self.get_object()
        
        # 检查权限
        if instance.shared_by != request.user:
            return Response(
                {'error': '没有权限删除此分享'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        instance.delete()
        
        # 记录活动日志
        ActivityLog.objects.create(
            user=request.user,
            action='delete_share',
            description=f'删除了笔记分享: {instance.note.title}'
        )
        
        return Response(status=status.HTTP_204_NO_CONTENT)
    
    @action(detail=False, methods=['get'])
    def public_shares(self, request):
        """获取公开分享列表"""
        shares = SharedNote.objects.filter(
            scope='public',
            is_active=True
        ).filter(
            Q(expires_at__isnull=True) | Q(expires_at__gt=timezone.now())
        ).select_related('note', 'shared_by').order_by('-created_at')
        
        page = self.paginate_queryset(shares)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        
        serializer = self.get_serializer(shares, many=True)
        return Response(serializer.data)
    
    @action(detail=True, methods=['get'], permission_classes=[permissions.AllowAny])
    def access(self, request, pk=None):
        """通过分享token访问笔记"""
        try:
            shared_note = SharedNote.objects.select_related('note').get(
                share_token=pk,
                is_active=True
            )
        except SharedNote.DoesNotExist:
            return Response(
                {'error': '分享不存在或已失效'},
                status=status.HTTP_404_NOT_FOUND
            )
        
        # 检查分享是否可访问
        if not shared_note.is_accessible:
            return Response(
                {'error': '分享已过期或达到访问限制'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        # 记录访问
        with transaction.atomic():
            ShareAccess.objects.create(
                shared_note=shared_note,
                visitor=request.user if request.user.is_authenticated else None,
                ip_address=request.META.get('REMOTE_ADDR'),
                user_agent=request.META.get('HTTP_USER_AGENT', ''),
                session_id=request.session.session_key
            )
            
            # 增加访问次数
            shared_note.access_count = F('access_count') + 1
            shared_note.save(update_fields=['access_count'])
        
        serializer = self.get_serializer(shared_note)
        return Response(serializer.data)
    
    @action(detail=True, methods=['get'])
    def statistics(self, request, pk=None):
        """获取分享统计信息"""
        shared_note = self.get_object()
        
        # 检查权限
        if shared_note.shared_by != request.user:
            return Response(
                {'error': '没有权限查看此分享统计'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        # 统计数据
        stats = {
            'total_access': shared_note.access_count,
            'unique_visitors': ShareAccess.objects.filter(
                shared_note=shared_note
            ).values('ip_address').distinct().count(),
            'comments_count': shared_note.comments.filter(
                is_approved=True, is_deleted=False
            ).count(),
            'recent_access': ShareAccess.objects.filter(
                shared_note=shared_note
            ).order_by('-accessed_at')[:10]
        }
        
        return Response(stats)


class ShareCommentViewSet(ModelViewSet):
    """分享评论视图集
    
    处理分享笔记的评论功能。
    """
    
    serializer_class = ShareCommentSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]
    
    def get_queryset(self):
        """获取查询集"""
        shared_note_id = self.request.query_params.get('shared_note')
        if shared_note_id:
            return ShareComment.objects.filter(
                shared_note_id=shared_note_id,
                is_approved=True,
                is_deleted=False
            ).select_related('author', 'shared_note').order_by('-created_at')
        
        return ShareComment.objects.none()
    
    @transaction.atomic
    def create(self, request, *args, **kwargs):
        """创建评论"""
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        # 设置评论者
        serializer.validated_data['author'] = request.user
        
        comment = serializer.save()
        
        # 记录活动日志
        ActivityLog.objects.create(
            user=request.user,
            action='comment_share',
            content_object=comment,
            description=f'评论了分享: {comment.shared_note.note.title}'
        )
        
        return Response(
            serializer.data,
            status=status.HTTP_201_CREATED
        )
    
    @action(detail=True, methods=['post'])
    def like(self, request, pk=None):
        """点赞评论"""
        comment = self.get_object()
        
        with transaction.atomic():
            like, created = CommentLike.objects.get_or_create(
                comment=comment,
                user=request.user
            )
            
            if not created:
                like.delete()
                return Response({'liked': False})
            
            return Response({'liked': True})
    
    @action(detail=True, methods=['post'])
    def report(self, request, pk=None):
        """举报评论"""
        comment = self.get_object()
        reason = request.data.get('reason', '')
        
        # 这里可以实现举报逻辑
        # 例如发送邮件给管理员、记录举报等
        
        return Response({'message': '举报已提交，感谢您的反馈'})


class ShareAccessViewSet(ModelViewSet):
    """分享访问记录视图集
    
    处理分享访问记录的查询。
    """
    
    serializer_class = ShareAccessSerializer
    permission_classes = [permissions.IsAuthenticated]
    http_method_names = ['get']  # 只允许查询
    
    def get_queryset(self):
        """获取查询集"""
        # 只能查看自己分享的访问记录
        return ShareAccess.objects.filter(
            shared_note__shared_by=self.request.user
        ).select_related('shared_note', 'visitor').order_by('-accessed_at')
